package com.lujieni.threadpool.service;

import com.lujieni.threadpool.context.ContextHolder;
import com.lujieni.threadpool.context.UserHolder;
import com.lujieni.threadpool.dao.ThreadPoolTaskDao;
import com.lujieni.threadpool.po.ThreadPoolTaskPO;
import com.lujieni.threadpool.po.User;
import com.lujieni.threadpool.task.SayContentTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class HelloService {

    @Autowired
    private ThreadPoolTaskExecutor lujieniAsyncPool;

    @Autowired
    private ExecutorService sayContentThreadPool;

    @Autowired
    private ThreadPoolTaskDao threadPoolTaskDao;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private ThreadPoolTaskExecutor taskDecoratorAsyncPool;

    @Autowired
    private ExecutorService ttlExecutorService;

    private int count = 0;

    @Async("lujieniAsyncPool")
    public void doA() throws InterruptedException {
        log.info("doA run");
        TimeUnit.SECONDS.sleep(5);
    }

    @Async("fuckAsyncPool")
    public void doB() throws InterruptedException {
        log.info("doB start");
        TimeUnit.SECONDS.sleep(30);
        System.out.println("doB end");
        log.info("doB end");
    }


    public void execute(){
        sayContentThreadPool.execute(()->{
            synchronized (this){
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                count++;
            }
        });
    }

    /**
     * 我和execute中的synchronized用的是同一把锁
     * @return
     */
    public synchronized int getCount(){
        return count;
    }


    public void useTaskDecorate(){
        taskDecoratorAsyncPool.execute(()->{
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            log.info("userCode:"+ ContextHolder.getContext().getUserCode());
        });
    }

    public void ttlExecutorService(){
        User user = new User();
        user.setName("lujieni");
        user.setAge(33);
        UserHolder.setUser(user);
        ttlExecutorService.execute(()->{
            try {
                TimeUnit.SECONDS.sleep(10);
                System.out.println(UserHolder.getUser());
            } catch (InterruptedException e) {

            }
          /*
            不必自己移除ttl会帮我们恢复环境
            finally {
               UserHolder.removeUser();
            }*/
        });
        UserHolder.removeUser(); // 主线程必须要移除
    }

    /**
     * 线程池中的线程读取别的线程中的对象也是可以的,原理是
     * jvm会把user这个字段拷贝到匿名内部类当中去
     */
    public void getUser(){
        User user = new User();
        user.setName(UUID.randomUUID().toString());
        ttlExecutorService.execute(()->{
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(user);
        });
    }

    public void taskRetry() {
        ThreadPoolTaskPO taskPO = new ThreadPoolTaskPO();
        taskPO.setActive(1);
        List<ThreadPoolTaskPO> threadPoolTaskPOS = threadPoolTaskDao.select(taskPO);
        threadPoolTaskPOS.forEach(e->{
            if(e.getTaskType().equals(SayContentTask.TASK_TYPE)){
                ExecutorService es = applicationContext.getBean(e.getPoolname(), ExecutorService.class);
                es.execute(new SayContentTask(e.getId(), e.getInput()));
            }
        });

    }
}
